﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PCControlCommand
{
    public class PipServer : Log
    {
        public Action<string> ReceiveEvent;
        NamedPipeServerStream m_pipServer;
        AutoResetEvent monitor = new AutoResetEvent(false);
        Thread m_thread;
        bool run = true;
        string servname;

        public PipServer(string name)
        {
            m_pipServer = new NamedPipeServerStream(name, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
            servname = name;
        }
        public void Listen()
        {
            while (run)
            {
                try
                {
                    WaitConnect();
                }
                catch (Exception ex)
                {
                    //P(ex, "[PipServer.WaitForConnect]");
                }
                Thread.Sleep(100);
            }
        }

        public void Stop()
        {
            run = false;
        }
        void WaitConnect()
        {
            AsyncCallback callback = null;
            callback = new AsyncCallback(ar =>
            {
                try
                {
                    var pipeServer = (NamedPipeServerStream)ar.AsyncState;
                    pipeServer.EndWaitForConnection(ar);
                    Accept();
                    pipeServer.Disconnect();
                    pipeServer.BeginWaitForConnection(callback, pipeServer);
                }
                catch
                {

                }
            });
            m_pipServer.BeginWaitForConnection(callback, m_pipServer);
        }


        void Accept()
        {
            try
            {
                var res = Read();
                if (!string.IsNullOrEmpty(res))
                {
                    Debug.WriteLine($"收到指令:{res}");
                    ReceiveEvent?.Invoke(res);
                }
            }
            catch (Exception ex)
            {
                //P(ex, "[PipServer.Accept]");
            }
        }
        public bool Send(string msg)
        {
            try
            {
                var buf = Encoding.UTF8.GetBytes(msg);
                if (m_pipServer.CanWrite)
                {
                    m_pipServer.Write(buf, 0, buf.Length);
                    m_pipServer.Flush();
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                //P(ex, "[PipServer.Send]");
                return false;
            }


        }

        public string Read()
        {
            try
            {
                if (m_pipServer.CanRead)
                {
                    int count = 0;
                    List<byte> data = new List<byte>();
                    byte[] buf = new byte[1024];
                    do
                    {
                        try
                        {
                            count = m_pipServer.Read(buf, 0, buf.Length);
                            if (count == buf.Length)
                            {
                                data.AddRange(buf);
                            }
                            else
                            {
                                var dst = new byte[count];
                                Buffer.BlockCopy(buf, 0, dst, 0, count);
                                data.AddRange(dst);
                            }
                        }
                        catch
                        {
                            break;
                        }
                    } while (count > 0 && m_pipServer.CanRead);
                    var res = Encoding.UTF8.GetString(data.ToArray());
                    return res;
                }
                return null;

            }
            catch (Exception ex)
            {
                // P(ex, "[PipServer.Read]");
                return null;
            }
        }

        public void Close()
        {
            run = false;
            m_thread.Join();
            if (m_pipServer.IsConnected)
            {
                m_pipServer.Close();
            }

        }
    }
    public class Log
    {
        public void L(string msg)
        {
            //Console.WriteLine(msg);
        }
        public void L(string format, params string[] data)
        {
            //Console.WriteLine(string.Format(format, data));
        }
        public void P(Exception ex, string format, params string[] data)
        {
            var msg = string.Format(format, data);
            //Console.WriteLine(string.Format("{0}:{1},{1}", msg, ex.Message, ex.StackTrace));
        }
    }
}
